package com.liliudong.pinkyponk.security.util;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.liliudong.pinkyponk.security.exception.JwtExpiredException;
import com.liliudong.pinkyponk.security.exception.JwtNotVerifyException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;

/**
 * Jwt工具类
 *
 * @author liliudong
 * @date 2022-05-27 15:51
 **/
@Component
public class JwtHelper {

    @Value("${jwt.expire}")
    private Integer expire;

    @Value("${jwt.sign-key}")
    private String signKey;

    private final static DateField DATE_FIELD = DateField.SECOND;

    public String generateToken(String userName) {
        HashMap<String, Object> payload = MapUtil.newHashMap();
        payload.put(JWT.SUBJECT, userName);
        payload.put(JWT.EXPIRES_AT,
                DateUtil.offset(DateUtil.date(), DATE_FIELD, expire).getTime());
        return JWTUtil.createToken(payload, getSignKeyBytes());
    }

    public String parseToken(String token) throws JwtNotVerifyException, JwtExpiredException {
        if (!JWTUtil.verify(token, getSignKeyBytes())) {
            throw new JwtNotVerifyException();
        }
        final JWT jwt = JWTUtil.parseToken(token);
        Long expireDateTime = Convert.toLong(jwt.getPayload(JWT.EXPIRES_AT));
        if (new Date(expireDateTime).before(DateUtil.date())) {
            throw new JwtExpiredException();
        }
        return Convert.toStr(jwt.getPayload(JWT.SUBJECT));
    }

    public Integer getExpire() {
        return expire;
    }

    public Long getExpireTimestamp() {
        return DateUtil.offset(new Date(), DateField.SECOND, expire).getTime();
    }

    private byte[] getSignKeyBytes() {
        return signKey.getBytes(StandardCharsets.UTF_8);
    }

}
